JVM总结相关笔记

JVM

JVM的参数设置

1. -Xms 初始堆大小  -Xmx 最大堆大小  [一般这两个值设置的是一样的,防止GC后出现内存抖动]
2. -Xmn 年轻代大小
    a) 整个堆的大小 = 年轻代大小 + 老年代大小 + 持久代大小
    b) 持久代一般固定大小为64M
    c) 所以,增大年轻代后,将会较小老年代的大小。这个值对系统性能影响较大,
       Sun官方推荐配置为整个堆的3/8
3. -XX:NewSize 初始年轻代大小     -XX:MaxNewSize 最大年轻代大小
4. -XX:NewRatio 老年代和年轻代的比值
5. -XX:SurvivorRatio 设置年轻代中Eden区与Survivor区的大小比值 
   [默认是8:1:1,比如设置为6,那么就是 6:2:2]
6. -XX:MaxTenuringThreshold 设置年轻代的对象被回收多少次后才进入老年代,默认15次
    [控制对象在经过多少次minor GC后进入老年代,此参数只在Serial串行GC时有效]
7. -XX:PermSize 初始持久代大小  -XX:MaxPermSize 持久代最大值 
    [这个跟 -Xms 和 -Xmx 堆大小设置一样,都是相等,为了防止内存抖动]

调优

JVM调优主要针对内存管理方面,包括控制各个代的大小,GC策略。
由于GC开始垃圾回收时会挂起应用线程,严重影响性能,调优的目的就是
为了尽量降低GC所导致的应用线程暂停时间、减少Full GC的次数。

代调优:

 1) 避免新生代大小设置过小
     当新生代设置过小时,会产生两种比较明显的现象:
         一是minor GC次数频繁
         二是可能导致minor GC对象直接进入老年代。当老年代内存不足时,会出发Full GC。
2) 避免新生代设置过大
    新生代设置过大,会带来两个问题:
        一是老年代变小,可能导致Full GC频繁执行;
        二是minor GC 执行回收的时间大幅度增加
那怎么选择年轻代的大小呢?[分不同的应用场景]
    a. 响应时间优先的应用:
        尽可能设大,知道接近系统的最低响应时间限制(根据实际情况选择)。


说明:新new的对象会首先会进入年轻代的Eden中(如果对象太大可能直接进入年老代),在GC之前对象是存在Eden和from中的,进行GC的时候Eden中的对象被拷贝到To这样一个survive空间(survive(幸存)空间:包括from和to,他们的空间大小是一样的,又叫s1和s2)中(有一个拷贝算法),From中的对象(算法会考虑经过GC幸存的次数)到一定次数 阈值(如果说每次GC之后这个对象依旧在Survive中存在,GC一次他的Age就会加1,默认15就会放到OldGeneration。但是实际情况比较复杂,有可能没有到阈值就从Survive区域直接到Old Generation区域。)

1.哪些需要回收? —-> java堆内存、方法区内存

2.什么时候回收? —–>

2.1:引用计数法【引用count+1,引用失效时count-1,为0时不被引用】
【如果两个对象相互引用而且都没有被使用了,那么会造成内存泄漏】。

2.2:可达性分析【从根节点搜索,如果没有搜索到就是没有被使用,所以互相引用且搜索不到的也会被清除】

怎么回收?—-> 垃圾回收算法[3种]

1.标记清除算法 [Mark-Sweep]

遍历所有的GC Root,分别标记处可达的对象和不可达的对象,然后将不可达的对象回收。
**缺点**是:效率低、回收得到的空间不连续 【当比较大的对象被创建时由于被回收的是不连续的,
所以被回收的空间就存不下,造成了浪费】

2.标记整理算法

将所有可用的对象往前移动[标记谁是活跃对象,整理,会把内存对象整理成一棵树一个连续的空间],这样会很耗资源

3.复制算法

将内存分为两块,每次只使用一块。当这一块内存满了,就将还存活的对象复制到另一块上,并且严格按照内存地址排列,然后把已使用的那块内存统一回收。
**优点**是:能够得到连续的内存空间 
**缺点**是:浪费了一半内存
年轻代使用的是复制整理算法
有一点需要注意: